// sparselizard - Copyright (C) see copyright file.
//
// See the LICENSE file for license information. Please report all
// bugs and problems to <alexandre.halbach at gmail.com>.


// This object stores the ROW-MAJOR values of a dense matrix of int.
// In other words the matrix is stored as [row1 row2 row3 ...].

#ifndef INTDENSEMATRIX_H
#define INTDENSEMATRIX_H

#include <iostream>
#include <vector>
#include <memory>

class intDenseMatrix
{   

    private:
        
        long long int numrows = 0;
        long long int numcols = 0;
        
        std::shared_ptr<int> myvalues = NULL;
        
        // Throws an error if matrix is empty:
        void errorIfEmpty(void);
        
    public:
        
        // Set empty matrix:
        intDenseMatrix(void) {};
        // Set number of rows and columns:
        intDenseMatrix(long long int numberofrows, long long int numberofcolumns);
        // Initialise to a value:
        intDenseMatrix(long long int numberofrows, long long int numberofcolumns, int initvalue);
        // Initialise with a vector (row major):
        intDenseMatrix(long long int numberofrows, long long int numberofcolumns, const std::vector<int> valvec);
        // Initialise to consecutive numbers [init init+step init+2*step ...].
        intDenseMatrix(long long int numberofrows, long long int numberofcolumns, int init, int step);
        
        long long int countRows(void) { return numrows; };
        long long int countColumns(void) { return numcols; };
        long long int count(void) { return numrows*numcols; };
        
        // Count the number of positive or zero integer values:
        long long int countPositive(void);
        // Count the number of occurences of a value:
        long long int countOccurences(long long int value);
        // Filter out the argument value and return a column vector:
        intDenseMatrix removeValue(long long int toremove);
        
        // Return a vector whose ith entry gives the number of times value i appears:
        std::vector<int> countAllOccurences(int maxintval);
        // And all indexes at which it appears:
        std::vector<std::vector<int>> findAllOccurences(int maxintval);

        // Sum all values:
        long long int sum(void);
        
        // Get the min and max values in out[0] and out[1] respectively:
        std::vector<int> minmax(void);
        
        int max(void);

        void print(void);
        void printSize(void);
 
        int* getValues(void);
        
        // Get the transpose without modifying this object.
        intDenseMatrix getTranspose(void);

        // A.duplicateAllRowsTogether(int n) for a matrix A of size pxq 
        // whose form is  [row1; row2; row3; ...] outputs a matrix of size 
        // (p*n)xq where every row of matrix A has been duplicated n 
        // times as follows [row1; row2; row3;  ... row1; row2; row3; ...].
        intDenseMatrix duplicateAllRowsTogether(int n);
        // A.duplicateRowsOneByOne(int n) for a matrix A of size pxq 
        // whose form is [row1; row2; row3; ...] outputs a matrix of size 
        // (p*n)xq where every row of matrix A has been duplicated n 
        // times as follows [row1; row1; row1;  ... row2; row2; row2; ...].
        intDenseMatrix duplicateRowsOneByOne(int n);
        // Same for columns:
        intDenseMatrix duplicateAllColsTogether(int n);
        intDenseMatrix duplicateColsOneByOne(int n);

        // Extract a set of rows/columns from the matrix:
        intDenseMatrix extractRows(std::vector<int>& selected);
        intDenseMatrix extractCols(std::vector<int>& selected);

};

#endif
